﻿' Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Utilities

Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator

    Friend NotInheritable Class PlaceholderLocalBinder
        Inherits Binder

        Private ReadOnly _containingMethod As MethodSymbol
        Private ReadOnly _allowImplicitDeclarations As Boolean
        Private ReadOnly _implicitDeclarations As Dictionary(Of String, LocalSymbol)

        Friend Sub New(
            aliases As ImmutableArray(Of [Alias]),
            containingMethod As MethodSymbol,
            typeNameDecoder As EETypeNameDecoder,
            allowImplicitDeclarations As Boolean,
            containingBinder As Binder)

            MyBase.New(containingBinder)
            _containingMethod = containingMethod
            _allowImplicitDeclarations = allowImplicitDeclarations

            _implicitDeclarations = New Dictionary(Of String, LocalSymbol)(CaseInsensitiveComparison.Comparer)
            For Each [alias] As [Alias] In aliases
                Dim local = PlaceholderLocalSymbol.Create(
                    typeNameDecoder,
                    containingMethod,
                    [alias])
                _implicitDeclarations.Add(local.Name, local)
            Next
        End Sub

        Friend Overrides Sub LookupInSingleBinder(
            result As LookupResult,
            name As String,
            arity As Integer,
            options As LookupOptions,
            originalBinder As Binder,
            <[In]> <Out> ByRef useSiteDiagnostics As HashSet(Of DiagnosticInfo))

            If (options And (LookupOptions.NamespacesOrTypesOnly Or LookupOptions.LabelsOnly Or LookupOptions.MustNotBeLocalOrParameter)) <> 0 Then
                Return
            End If

            Dim local As LocalSymbol = Nothing
            If _implicitDeclarations.TryGetValue(name, local) Then
                result.SetFrom(CheckViability(local, arity, options, Nothing, useSiteDiagnostics))
            End If
        End Sub

        Public Overrides ReadOnly Property ImplicitVariableDeclarationAllowed As Boolean
            Get
                Return _allowImplicitDeclarations
            End Get
        End Property

        Public Overrides Function DeclareImplicitLocalVariable(nameSyntax As IdentifierNameSyntax, diagnostics As DiagnosticBag) As LocalSymbol
            Debug.Assert(_allowImplicitDeclarations)
            Debug.Assert(_implicitDeclarations IsNot Nothing)

            Dim identifier = nameSyntax.Identifier
            Dim typeChar As String = Nothing
            Dim specialType = GetSpecialTypeForTypeCharacter(identifier.GetTypeCharacter(), typeChar)
            Dim type = Compilation.GetSpecialType(If(specialType = SpecialType.None, SpecialType.System_Object, specialType))
            Dim name = identifier.GetIdentifierText()
            Dim local = LocalSymbol.Create(
                _containingMethod,
                Me,
                identifier,
                LocalDeclarationKind.ImplicitVariable,
                type,
                name)
            _implicitDeclarations.Add(name, local)
            If name.StartsWith("$", StringComparison.Ordinal) Then
                diagnostics.Add(ERRID.ERR_IllegalChar, identifier.GetLocation())
            End If
            Return local
        End Function

        Friend Overrides Sub AddLookupSymbolsInfoInSingleBinder(nameSet As LookupSymbolsInfo, options As LookupOptions, originalBinder As Binder)
            Throw New NotImplementedException()
        End Sub

    End Class

End Namespace

